package com.the_ring.chapter12.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

/**
 * int offset = 5;
 * mv_mosaic.setOffset(offset);
 * ObjectAnimator anim = ObjectAnimator.ofInt(mv_mosaic, "ratio", 0 - offset, 101 + offset);
 * anim.setDuration(3000);
 * anim.start();
 */
public class MosaicView extends View {

    private Paint paint = new Paint();
    private int orientation = LinearLayout.HORIZONTAL;
    private int gridCount = 60; // 格子的数量
    private PorterDuff.Mode mode = PorterDuff.Mode.DST_IN; // 只展示交集
    private Bitmap mBitmap;
    private int ratio = 0;  // 绘制的比率
    private int offset = 5; // 偏差的比例
    // private float FENMU = 100;

    private boolean initTag = true;     // 首次绘制
    private RectF rectF;

    public MosaicView(Context context) {
        this(context, null);
    }

    public MosaicView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mBitmap == null) {
            return;
        }
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        // 创建一个遮罩层
        Bitmap mask = Bitmap.createBitmap(width, height, mBitmap.getConfig());
        Canvas canvasMask = new Canvas(mask);
        if (orientation == LinearLayout.HORIZONTAL) {
            float gridWidth = height / gridCount; // 格子宽度
            int columnCount = (int) Math.ceil(width / gridWidth);
            int totalCount = gridCount * columnCount;
            int drawCount = 0;
            for (int i = 0; i < columnCount; i++) {
                for (int j = 0; j < gridCount; j++) {
                    int nowRatio = (gridCount * i + j) * 100 / totalCount; // 当前绘制格子所在比例
                    if (nowRatio < ratio - offset
                            || (nowRatio >= ratio - offset && nowRatio < ratio && ((j % 2 == 0 && i % 2 == 0) || (j % 2 == 1 && i % 2 == 1)))
                            || (nowRatio >= ratio && nowRatio < ratio + offset && ((j % 2 == 0 && i % 2 == 1) || (j % 2 == 1 && i % 2 == 0)))) {
                        int left = (int) (gridWidth * i);
                        int top = (int) (gridWidth * j);
                        // 在遮罩层上绘制各方形格子
                        canvasMask.drawRect(left, top, left + gridWidth, top + gridWidth, paint);
                        if (j < gridCount) {
                            drawCount++;
                        }
                        if (drawCount * 100 / totalCount > ratio) {
                            break;
                        }
                    }
                }
                if (drawCount * 100 / totalCount > ratio) {
                    break;
                }
            }
        } else {
            float gridWidth = width / gridCount;
            int rowCount = (int) Math.ceil(height / gridWidth);
            int totalCount = gridCount * rowCount;
            int drawCount = 0;
            for (int i = 0; i < rowCount; i++) {
                for (int j = 0; j < gridCount; j++) {
                    int nowRatio = (gridCount * i + j) * 100 / totalCount;
                    if (nowRatio < ratio - offset
                            || (nowRatio >= ratio - offset && nowRatio < ratio && ((j % 2 == 0 && i % 2 == 0) || (j % 2 == 1 && i % 2 == 1)))
                            || (nowRatio >= ratio && nowRatio < ratio + offset && ((j % 2 == 0 && i % 2 == 1) || (j % 2 == 1 && i % 2 == 0)))) {
                        int left = (int) (gridWidth * i);
                        int top = (int) (gridWidth * j);
                        // 在遮罩层上绘制各方形格子
                        canvasMask.drawRect(left, top, left + gridWidth, top + gridWidth, paint);
                        if (j < gridCount) {
                            drawCount++;
                        }
                        if (drawCount * 100 / totalCount > ratio) {
                            break;
                        }
                    }
                }
                if (drawCount * 100 / totalCount > ratio) {
                    break;
                }
            }
        }

        int saveLayer = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);

        // 计算图片的显示位置
        if (initTag) {
            if (mBitmap.getWidth() / width > mBitmap.getHeight() / height) {
                int realWidth = width;
                int realHeight = width * mBitmap.getHeight() / mBitmap.getWidth();
                rectF = new RectF(0, (height - realHeight) / 2, width, (height + realHeight) / 2);
            } else {
                int realWidth = height * mBitmap.getWidth() / mBitmap.getHeight();
                int realHeight = height;
                rectF = new RectF((width - realWidth) / 2, 0, (width + realWidth) / 2, height);
            }
            initTag = false;
        }

        canvas.drawBitmap(mBitmap, null, rectF, paint);
        paint.setXfermode(new PorterDuffXfermode(mode));
        canvas.drawBitmap(mask, 0, 0, paint);
        paint.setXfermode(null);
        canvas.restoreToCount(saveLayer);
    }

    public void setBitmap(Bitmap mBitmap) {
        this.mBitmap = mBitmap;
        initTag = true;
    }

    public void setMode(PorterDuff.Mode mode) {
        this.mode = mode;
    }

    public void setOffset(int offset) {
        this.offset = offset;
    }

    public void setRatio(int ratio) {
        this.ratio = ratio;
        postInvalidate();
    }
}
